package io.github.junxworks.qt.commons;

import java.util.Date;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import io.github.junxworks.junx.core.util.ClockUtils;
import io.github.junxworks.junx.core.util.ClockUtils.Clock;
import io.github.junxworks.junx.core.util.DateUtils;
import io.github.junxworks.junx.core.util.StringUtils;
import io.github.junxworks.qt.modules.tushare.TushareConstants;
import io.github.junxworks.qt.modules.tushare.service.BaseInfoService;

public class DateHandleService {

	protected static final String TODAY = "today";

	protected static final String YDAY = "yesterday";

	@Lazy
	@Autowired
	private BaseInfoService baseInfoService;

	/**
	 * 按日期执行
	 *
	 * @param date the date
	 * @param consumer the consumer
	 */
	public void handleDataByDate(String date, Consumer<String> consumer) {
		if (TODAY.equalsIgnoreCase(date)) {
			date = DateUtils.format(new Date(), TushareConstants.TUSHARE_DATE_FORMAT);
		}
		if (YDAY.equalsIgnoreCase(date) || StringUtils.isNull(date)) {
			date = DateUtils.format(DateUtils.addDays(new Date(), -1), TushareConstants.TUSHARE_DATE_FORMAT); //默认昨天的交易数据
		}
		consumer.accept(date);
	}

	public void collectTradeDataByDateRange(String range, Consumer<String> consumer) {
		handleDataDayByDay(range, 0, consumer);
	}

	/**
	 * 处理上月末的数据，一般是财报期，例如4月1号取3月31号的数据
	 * @param date
	 */
	public void handleDataByLastFinanceReportPeriod(String currentDate, Consumer<String> consumer) {
		handleDataByDate(currentDate, (d) -> {
			String date = queryRecentFinancePeriod(d);
			consumer.accept(date);
		});
	}

	public String queryRecentFinancePeriod(String date) {
		List<Integer> periods = baseInfoService.getFinancePeriods();
		Integer d = Integer.valueOf(date);
		for (Integer p : periods) {
			if (p <= d) {
				return String.valueOf(p);
			}
		}
		return null;
	}

	/**
	 * 处理财报期的数据，日期天数传财报期后一个月的第一天
	 * 例如：dateRange传20230101,20231001，那么消费的date就是20221231，20230331，20230630，20230930
	 * 以上日期都是财报期的end_date
	 * 
	 * @param dateRange
	 * @param consumer
	 */
	public void handleDataByLastFinanceReportPeriodRange(String dateRange, Consumer<String> consumer) {
		handleDataQuarterByQuarter(dateRange, d -> {
			handleDataByLastFinanceReportPeriod(d, consumer);
		});
	}

	/**
	 * 区间按天执行
	 *
	 * @param range the range
	 * @param consumer the consumer
	 */
	public void handleDataDayByDay(String range, long interval, Consumer<String> consumer) {
		String[] ranges = range.split(",");
		String begin = ranges[0];
		String end = ranges[1];
		Date beginDate = DateUtils.parseDate(begin, TushareConstants.TUSHARE_DATE_FORMAT);
		Date endDate = DateUtils.parseDate(end, TushareConstants.TUSHARE_DATE_FORMAT);
		Date tradeDate = beginDate;
		Clock counter = ClockUtils.createClock();
		while (tradeDate.getTime() <= endDate.getTime()) {
			consumer.accept(DateUtils.format(tradeDate, TushareConstants.TUSHARE_DATE_FORMAT));
			tradeDate = DateUtils.addDays(tradeDate, 1);
			long cost = counter.countMillisAndReset();
			long sleepTime = interval - cost; //时间控制在1秒钟1次接口
			if (sleepTime > 0) {
				try {
					Thread.sleep(sleepTime);
				} catch (InterruptedException e) {
				}
			}
		}
	}

	/**
	 * 区间按月执行
	 *
	 * @param range the range
	 * @param consumer the consumer
	 */
	public void handleDataWeekByWeek(String range, Consumer<String> consumer) {
		handleDataByInterval(range, consumer, d -> {
			return DateUtils.addDays(d, 7);
		});
	}

	/**
	 * 区间按月执行
	 *
	 * @param range the range
	 * @param consumer the consumer
	 */
	public void handleDataMonthByMonth(String range, Consumer<String> consumer) {
		handleDataByInterval(range, consumer, d -> {
			return DateUtils.parseDate(DateUtils.lastDayOfMonth(DateUtils.addMonths(d, 1)));
		});
	}

	/**
	 * 区间按季度执行
	 *
	 * @param range the range
	 * @param consumer the consumer
	 */
	public void handleDataQuarterByQuarter(String range, Consumer<String> consumer) {
		handleDataByInterval(range, consumer, d -> {
			return DateUtils.parseDate(DateUtils.lastDayOfMonth(DateUtils.addMonths(d, 3)));
		});
	}

	private void handleDataByInterval(String range, Consumer<String> consumer, Function<Date, Date> intervalFunc) {
		String[] ranges = range.split(",");
		String begin = ranges[0];
		String end = ranges[1];
		Date beginDate = DateUtils.parseDate(begin, TushareConstants.TUSHARE_DATE_FORMAT);
		Date endDate = DateUtils.parseDate(end, TushareConstants.TUSHARE_DATE_FORMAT);
		Date tradeDate = beginDate;
		while (tradeDate.getTime() <= endDate.getTime()) {
			consumer.accept(DateUtils.format(tradeDate, TushareConstants.TUSHARE_DATE_FORMAT));
			tradeDate = intervalFunc.apply(tradeDate);
		}
	}

}
